home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech's Sprocket™ / SprocketGX / Lib / AppLib.cp < prev    next >
Encoding:
Text File  |  1994-10-18  |  18.6 KB  |  706 lines  |  [TEXT/MMCC]

  1. /*
  2.     File:        AppLib.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.      Oct 5, 94:    Added GXDocWindow
  13.          Global initialisation moved into main as Think Debugger doesnt like StdLib initialisation calling ToolBox!
  14.         Discovered CodeWarrior cannot call ANY GX trap properly: returns result in A0 not D0 !
  15.         
  16. */
  17. #ifdef    SystemSevenOrLater
  18.     #undef    SystemSevenOrLater
  19. #endif
  20. #define    SystemSevenOrLater    1
  21.  
  22. #include <limits.h>        //    For LONG_MAX
  23.  
  24. #include <Types.h>
  25. #include <Quickdraw.h>
  26. #include <Fonts.h>
  27. #include <Menus.h>
  28. #include <Windows.h>
  29. #include <Dialogs.h>
  30. #include <Desk.h>
  31. #include <Events.h>
  32. #include <AppleEvents.h>
  33. #include <DiskInit.h>
  34.  
  35. #if qUseETO15Interfaces
  36.     #include <Gestalt.h>
  37.     #include <CodeFragments.h>
  38.     #include <Devices.h>
  39. #else    // qUseETO15Interfaces
  40.     #include <GestaltEqu.h>
  41.     #include <FragLoad.h>
  42. #endif    // qUseETO15Interfaces
  43.  
  44. #include <ToolUtils.h>
  45. #include <Traps.h>
  46. #include <LowMem.h>
  47.  
  48. #include <Threads.h>
  49. #include <Drag.h>
  50. #include <Editions.h>
  51. //#include <OCEStandardMail.h>
  52.  
  53. #if    qInlineInputAware
  54.     #include <TextServices.h>
  55.     #include <TSMTE.h>
  56. #endif    // qInlineInputAware
  57.  
  58. #include "AppLib.h"
  59. #include "StandardMenus.h"
  60. #include "Window.h"
  61. #include "SplashWindow.h"
  62. #include "MailableWindow.h"
  63. #include "AppleEventHandling.h"
  64. #include "QDGXHeaders.h"
  65.  
  66.  
  67. //    Function Prototypes
  68.  
  69. void    main(void);
  70. void    MainEventLoop(void);
  71.  
  72. void    HandleMouseDown(TWindow * theWindowObj, EventRecord * pEvent);
  73. void    HandleUpdate(EventRecord * pEvent);
  74. void    HandleClose(WindowPtr pWindow);
  75. void WindowCommand(WindowPtr pWindow, short theMenuID, short theItem);
  76.  
  77. //    Globals
  78.  
  79. Boolean                gDone = false;
  80. Boolean                gMenuBarNeedsUpdate = true;
  81.  
  82. Boolean                gHasColorQuickdraw = false;
  83. Boolean                gHasThreadManager = false;
  84. Boolean                gHasDragManager = false;
  85. Boolean                gHasAppleScript = false;
  86. Boolean                gHasAOCE = false;
  87. Boolean                gHasDisplayManager = false;
  88.  
  89. GrafPtr                gWindowManagerPort;
  90. Rect                    gDeskRectangle;
  91. RgnHandle            gMouseRegion = nil;
  92.  
  93. short                gPreferencesRsrcRefNum;
  94.  
  95. #if    qInlineInputAware
  96.     Boolean                gHasTextServices = false;
  97.     Boolean                gHasTSMTE = false;
  98. #endif
  99.  
  100. #if    qUseQuickDrawGX
  101.     Boolean                gHasQuickDrawGX = false;
  102.     Boolean                gGXDebugging = false;
  103.     Boolean                gGXValidation = false;
  104.     long                    gQuickDrawGXVersion = 0;
  105.     long                    gQuickDrawGXPrintingVersion = 0;
  106.     gxGraphicsClient    gQuickDrawGXClient = nil;
  107. #endif
  108.  
  109. //    Values that can be adjusted by other application code to change
  110. //    the behavior of the MainEventLoop.
  111. //
  112. //    Rules of thumb:
  113. //
  114. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  115. //            The application has many threads running that need time
  116. //
  117. //        Decrease gXXXRunQuantum when:
  118. //            Sending AppleEvents to other applications
  119. //            Launching other applications
  120. //            Running in the background
  121.  
  122. // Think Debugger doesnt like StdLib initialisation calling ToolBox
  123. unsigned long    gForegroundRunQuantum = 0;
  124. unsigned long    gForegroundSleepQuantum = 4;    // Δ in InitializeToolBox
  125. unsigned long    gBackgroundRunQuantum = 0;
  126. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  127.  
  128. //    Globals used to “tune” the performance of MainEventLoop
  129. //    (assume we’ll be starting in the foreground)
  130.  
  131. static    unsigned long    gRunQuantum;
  132. static    unsigned long    gSleepQuantum;
  133.  
  134. #ifdef    powerc
  135.     #ifndef    __MWERKS__
  136.         QDGlobals    qd;
  137.     #endif
  138. #endif
  139.  
  140. const short kMaxShort = 32767;
  141. #define        Minimum(a, b)     ((a) < (b) ? (a) : (b))
  142.  
  143. void    InitializeToolBox(short theNumOfCallsToMoreMasters);
  144. void    InitializeToolBox(short theNumOfCallsToMoreMasters)
  145. {
  146.     // Generic heap initialization.
  147.     MaxApplZone();
  148.     {
  149.         THz         pApplZone = ApplicationZone();
  150.         short     aSaveMoreMast = pApplZone->moreMast;
  151.         long         aNumMasterPointersDesired = aSaveMoreMast * theNumOfCallsToMoreMasters;
  152.  
  153.         // Here is a trick suggested by Jerome C.--it allocates one large block of master pointers
  154.         for
  155.         (
  156.             aNumMasterPointersDesired = aSaveMoreMast * theNumOfCallsToMoreMasters;
  157.             aNumMasterPointersDesired > 0;
  158.             aNumMasterPointersDesired -= pApplZone->moreMast
  159.         )
  160.         {
  161.             pApplZone->moreMast = (short)Minimum(aNumMasterPointersDesired, kMaxShort);
  162.             MoreMasters();
  163.         }
  164.         pApplZone->moreMast = aSaveMoreMast;
  165.     }
  166.     
  167.     // Think Debugger doesnt like StdLib initialisation calling ToolBox
  168.     gForegroundSleepQuantum = GetCaretTime();
  169.     gRunQuantum = gForegroundRunQuantum;
  170.     gSleepQuantum = gForegroundSleepQuantum;
  171.  
  172.     // Start up the toolbox so we can notify people if there's a problem
  173.     InitGraf(&qd.thePort);    
  174.     InitFonts();
  175.     InitWindows();
  176.     InitMenus();
  177.     TEInit();
  178.     InitDialogs(nil);
  179. }
  180.  
  181. void main(void)
  182. {
  183.     long        feature;
  184.     
  185.     InitializeToolBox(6);
  186.     
  187.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  188.         FatalErrorAlert(kCoreErrorStrings, kUnsupportedSystemSoftware);
  189.  
  190.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  191.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  192.  
  193. #if    qUseQuickDrawGX
  194.     //    Check for and initialize QuickDrawGX
  195.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  196.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  197. #ifdef    powerc
  198.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  199.                 gHasQuickDrawGX = true;
  200. #else
  201.             gHasQuickDrawGX = true;
  202. #endif
  203.  
  204.     if (gHasQuickDrawGX)
  205.     {
  206. // Initialize the graphics and printing environments. For additional details see "IM: QD GX Env & Utes."
  207.         OSErr        anErr = 1;    // initialize for failure of GXNewGraphicsClient
  208.         // The GXNewGraphicsClient routine defines the graphics heap size.  If you do not make this
  209.         // call, the GX graphics engine will create this heap automatically.  How?  It will create
  210.         // a heap which is a percentage of your application's ideal memory foot print.  This call
  211.         // allows you to explicity define the ammount of memory used by the graphics system for
  212.         // its graphics objects heap.
  213.         // If you pass zero for the memoryLength (2nd) parameter, QuickDraw GX looks for a resource 
  214.         // of type 'gasz' with an ID of 0 and uses the first long word of that resource as the heap size. 
  215.         // If your application does not provide this resource, QuickDraw GX version 1.0 uses a default size of 600 KB.
  216.         // gxClientAttribute: 0 = GX can expand heap, 1 (gxStaticHeapClient) = static heap
  217.         // To determine the memory requirements of your graphics client heap: See IM: QD GX Env & Utes pp2-8,2-9
  218.  
  219.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kGraphicsHeapSize, (gxClientAttribute) 0);
  220.         if (gQuickDrawGXClient)
  221.         {
  222.             // NB: GXNewGraphicsClient() does not allocate memory to the heap yet.     
  223.             // This requires the GXEnterGraphics function call.
  224.             GXEnterGraphics();
  225.  
  226.             anErr = GXGetGraphicsError(nil);
  227.             // GXEnterGraphics() would fail only if there is not enough memory. 
  228.             // In this case, the graphics error posted is -27999 (out of memory).
  229.             if (anErr != out_of_memory)
  230.             {
  231.                 // Set gGXValidation to TRUE if you want run-time validation. As you increase the amount
  232.                 // of validation, The drawing speed will SLOW down due to all of the internal checking. 
  233.                 if (gGXValidation)
  234.                 {
  235.                     gxValidationLevel        aValidationLevel = gxPublicValidation;    // check parameters to public routines
  236.     
  237.         //        aValidationLevel |= gxInternalValidation;
  238.         //        aValidationLevel |= gxAllObjectValidation;
  239.         //        aValidationLevel |= gxApHeapValidation;
  240.         // NB: Play with these enough and Validation becomes inconsistent
  241.                     GXSetValidation(aValidationLevel); 
  242.                 }
  243.  
  244.                 // If gGXDebugging = TRUE, you will receive graphics library errors & notices will be posted.
  245.                 // This functionality will only work with the "debugging" version of QuickDraw GX.  If you
  246.                 // don't have the debugging version installed, these functions will not work. 
  247.                 if (gGXDebugging) 
  248.                 {
  249.                     SetGraphicsLibraryErrors();
  250.                     SetGraphicsLibraryNotices();    
  251.                 }
  252.                 anErr = GXInitPrinting();    // See IM: QD GX Printing
  253.             }
  254.         }
  255.         if (anErr)
  256.         {
  257.             if (gQuickDrawGXClient)
  258.                 GXDisposeGraphicsClient(gQuickDrawGXClient);
  259.             gHasQuickDrawGX = false;
  260.         }
  261.     }
  262.     if (gHasQuickDrawGX == false)
  263.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  264.     
  265. #endif
  266.             
  267.     TSplashWindow * splashWindow = new TSplashWindow;
  268.     
  269.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  270.         (feature & (1 << gestaltAppleEventsPresent)))
  271.     {
  272.         //    Figure out if we need to do AppleEvent recording
  273.         gHasAppleScript = (feature & (1 << gestaltScriptingSupport));
  274.     }
  275.     else
  276.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  277.  
  278. #if    qInlineInputAware
  279.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  280.     {
  281.         gHasTextServices = true;
  282.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  283.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  284.     }
  285. #endif
  286.  
  287.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  288.     {
  289. #ifdef    powerc
  290.         //    If running on a PowerPC, make sure that we not only have the
  291.         //    68K Thread Manager, but also the PowerPC shared library, too.
  292.         //    Because of the wonders of weak linking and out of memory errors
  293.         //    we need to also check to make sure that an entrypoint in the library
  294.         //    is there, too. 
  295.         if ((Ptr) NewThread != kUnresolvedSymbolAddress)
  296.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  297. #else
  298.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  299. #endif
  300.     }
  301.         
  302.     //    Check for and install Drag Manager callbacks
  303.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  304.     {
  305. #ifdef    powerc
  306.         //    If running on a PowerPC, make sure that we not only have the
  307.         //    68K Drag Manager, but also the PowerPC shared library, too.
  308.         if ((Ptr) NewDrag != kUnresolvedSymbolAddress)
  309.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  310. #else
  311.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  312. #endif
  313.  
  314.         if (gHasDragManager)
  315.         {
  316.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  317.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  318.         }
  319.     }
  320.  
  321.     //    Check for Display Manager
  322.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  323.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  324.     
  325.     //    Check for and initialize AOCE Standard Mail package if it exists
  326.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  327.     {
  328. #ifdef    powerc
  329.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  330.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  331. #else
  332.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  333. #endif
  334.     }
  335.  
  336.     //    Install our AppleEvent Handlers
  337.     InstallAppleEventHandlers();
  338.  
  339.     //    Setup desktop rectangle for dragging windows around            
  340.     GetWMgrPort(&gWindowManagerPort);
  341.     gDeskRectangle = (*GetGrayRgn())->rgnBBox;
  342.  
  343.     //    Get the default menubar
  344.     SetMenuBar(GetNewMBar(rMenuBar));
  345.     AddResMenu(GetMHandle(mApple),'DRVR');
  346.  
  347. #if    qUseQuickDrawGX
  348.     if (gQuickDrawGXClient)
  349.     {
  350.         // We initialize the CommonColors Library.  This will allow us to set the color of a
  351.         // shape by calling the SetShapeCommonColor function. We will need to call
  352.         // DisposeCommonColors when we leave, to clean up the world.
  353.         InitCommonColors();
  354.     }
  355. #endif
  356.     
  357.     gPreferencesRsrcRefNum = OpenPreferencesResFile();
  358.     
  359.     if (SetupApplication() == noErr)
  360.     {
  361.         delete    splashWindow;    //    get rid of the splash screen
  362.         MainEventLoop();
  363.         TearDownApplication();
  364.     }
  365.         
  366. #if    qUseQuickDrawGX
  367.     // Leaving.  Close all the windows so we get rid of any data we or GX created.  Then,
  368.     // dispose of the common colors and exit the GX printing and graphics environment.
  369.     if (gHasQuickDrawGX && gQuickDrawGXClient)        //    Tear down QuickDrawGX
  370.     {
  371.         DisposeCommonColors();
  372.         GXExitPrinting();        // Close the new printing mgr. 
  373.         GXExitGraphics();        // Deallocate all of the default structures
  374.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  375.     }
  376. #endif
  377.     return;
  378. }
  379.  
  380. void MainEventLoop(void)
  381. {
  382.     EventRecord        anEvent;
  383.     unsigned long    nextTimeToCheckForEvents = 0;
  384.     
  385.     while (! gDone)
  386.     {
  387.         if (gMenuBarNeedsUpdate)
  388.         {
  389.             gMenuBarNeedsUpdate = false;
  390.             DrawMenuBar();
  391.         }
  392.             
  393.         if ((gRunQuantum == 0) ||
  394.             (TickCount() > nextTimeToCheckForEvents))
  395.         {
  396.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  397.             
  398.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  399.                         
  400.             HandleEvent(&anEvent);
  401.         }
  402.  
  403.         if (gHasThreadManager)
  404.             YieldToAnyThread();
  405.     }
  406. }
  407.  
  408. void HandleEvent(EventRecord *pEvent)
  409. {
  410.     TWindow* pWindObj;
  411.     
  412.     pWindObj = GetWindowObject((pEvent->what == updateEvt) ? ((WindowPtr)pEvent->message) : FrontNonFloatingWindow());
  413.  
  414.     if (pWindObj)
  415.     {
  416.         pWindObj->AdjustCursor(pEvent);
  417.         if (pWindObj->EventFilter(pEvent))
  418.             return;
  419.     }
  420.         
  421.     switch (pEvent->what)
  422.     {
  423.         case    nullEvent:
  424.             if (pWindObj)
  425.                 pWindObj->Idle(pEvent);
  426.             else
  427.                 InitCursor();
  428.             break;
  429.             
  430.         case    mouseDown:
  431.             HandleMouseDown(pWindObj, pEvent);
  432.             break;
  433.         
  434.         case    keyDown:
  435.         case    autoKey:
  436.             if (pEvent->modifiers & cmdKey)
  437.             {
  438.                 HandleSetupMenus(pWindObj);
  439.                 HandleMenu(pWindObj, MenuKey((short) pEvent->message & charCodeMask));
  440.             }
  441.             else 
  442.                 if (pWindObj)
  443.                     pWindObj->KeyDown(pEvent);
  444.             break;
  445.             
  446.         case    updateEvt:
  447.             HandleUpdate(pEvent);
  448.             break;
  449.             
  450.         case diskEvt:
  451.             if (pEvent->message >> 16)
  452.             {
  453.                 static    Point    where = {50,50};
  454.                 (void)DIBadMount(where, pEvent->message);
  455.             }
  456.             break;
  457.                 
  458.         case    osEvt:
  459.             switch ((pEvent->message & osEvtMessageMask) >> 24)
  460.             {
  461.                 case    mouseMovedMessage:
  462.                     break;
  463.                     
  464.                 case    suspendResumeMessage:                    
  465.                     if (pEvent->message & resumeFlag)
  466.                     {
  467.                         gRunQuantum = gForegroundRunQuantum;
  468.                         gSleepQuantum = gForegroundSleepQuantum;
  469.                     }
  470.                     else
  471.                     {
  472.                         gRunQuantum = gBackgroundRunQuantum;
  473.                         gSleepQuantum = gBackgroundSleepQuantum;
  474.                     }
  475.  
  476.                     SuspendResumeWindows((pEvent->message & resumeFlag) != 0);
  477.                     if (pEvent->message & convertClipboardFlag)
  478.                         ConvertClipboard();
  479.                     break;
  480.             }
  481.             break;
  482.         
  483.         case    kHighLevelEvent:
  484.             (void) AEProcessAppleEvent(pEvent);
  485.             break;
  486.             
  487.         default:
  488.             break;
  489.     }
  490. }
  491.  
  492. // Private structure of a MenuBar as returned by _GetMenuBar
  493. typedef        struct    // PrivateMenuData
  494. {
  495.     MenuHandle        menuHdl;
  496.     short                menuID;
  497. } PrivateMenuData, *PrivateMenuDataPtr;
  498.  
  499. typedef        struct    // PrivateMBarData
  500. {
  501.     Handle        menuBarH;
  502.     short        menuBarID;
  503. } PrivateMBarData;
  504.  
  505. typedef        struct    // PrivateMenuBar
  506. {
  507.     PrivateMBarData        mBar;
  508.     PrivateMenuData        menuArr[1];    // NB: list terminated with null menuHdl
  509. } PrivateMenuBar, *PrivateMenuBarPtr, **PrivateMenuBarHdl;
  510.  
  511. void  EnableAllMenus(Boolean theEnableFlag)
  512. {
  513.     Handle        hMbar = GetMenuBar();        // no fail on GetMenuBar()
  514.     short    aMenuCount = (GetHandleSize(hMbar)-sizeof(PrivateMBarData))/sizeof(PrivateMenuData);
  515.     PrivateMenuDataPtr        pMenuData = (*(PrivateMenuBarHdl)hMbar)->menuArr;
  516.     
  517.     HLock(hMbar);
  518.     while (aMenuCount-- > 0)
  519.     {
  520.         short    aItemCount;
  521.         if (pMenuData->menuHdl)    // list terminates with null menuHdl 
  522.             for (aItemCount = CountMItems(pMenuData->menuHdl); aItemCount > 0; --aItemCount)
  523.                 // DONT touch item 0: this means ALL items
  524.                 if (theEnableFlag)
  525.                     EnableItem(pMenuData->menuHdl, aItemCount);
  526.                 else
  527.                     DisableItem(pMenuData->menuHdl, aItemCount);
  528.         ++pMenuData;
  529.     }
  530.     DisposeHandle(hMbar);
  531.     DrawMenuBar();
  532. }
  533.  
  534. void  EnableOneMenu(short theMenuID, Boolean theEnableFlag)
  535. {
  536.     MenuHandle    hMenu = GetMHandle(theMenuID);
  537.     short    aItemCount;
  538.     if (hMenu)
  539.         for (aItemCount = CountMItems(hMenu); aItemCount > 0; --aItemCount)
  540.             // DONT touch item 0: this means ALL items
  541.             if (theEnableFlag)
  542.                 EnableItem(hMenu, aItemCount);
  543.             else
  544.                 DisableItem(hMenu, aItemCount);
  545. }
  546.  
  547. void  EnableMenuItem(short theMenuID, short theItem, Boolean theEnableFlag)
  548. {
  549.     MenuHandle    hMenu = GetMHandle(theMenuID);
  550.     if (hMenu && theItem)    // DONT touch item 0: this means ALL items
  551.         if (theEnableFlag)
  552.             EnableItem(hMenu, theItem);
  553.         else
  554.             DisableItem(hMenu, theItem);
  555. }
  556.  
  557. void  UpdateWindowMenu(void)
  558. {
  559.     MenuHandle        hMenu = GetMHandle(mWindows);
  560.     if (hMenu)
  561.     {
  562.         Str63            aName;
  563.         WindowPtr    pWindow;
  564.         TWindow*         topWindowObj = nil;
  565.         short            aItemCount;
  566.         
  567.         for (aItemCount = CountMItems(hMenu);  (aItemCount > iDivider1mWindows); --aItemCount)
  568.             DelMenuItem(hMenu, aItemCount);
  569.         // Walk the window list for Windows menu
  570.         for (pWindow = FrontNonFloatingWindow(); pWindow; pWindow = (WindowPtr)((WindowPeek)pWindow)->nextWindow)
  571.         {
  572.             TWindow    *pWindObj = GetWindowObject(pWindow);
  573.             if (pWindObj)
  574.             {
  575.                 GetWTitle(pWindow, aName);
  576.                 aItemCount = 1+CountMItems(hMenu);    // append new item
  577.                 InsMenuItem(hMenu, "\p•", aItemCount);        // aName wont be parsed
  578.                 SetItem(hMenu, aItemCount, aName);
  579.                 if (topWindowObj == nil)
  580.                 {    // this is frontmost TWindow
  581.                     topWindowObj = pWindObj;
  582.                     CheckItem(hMenu, aItemCount, true);
  583.                 }
  584.             }
  585.         }
  586.     }
  587.     EnableOneMenu(mWindows, true);
  588. }
  589.  
  590. void HandleSetupMenus(TWindow * topWindowObj)
  591. {
  592.     EnableAllMenus(false);
  593.     EnableOneMenu(mApple, true);
  594.     
  595.     EnableMenuItem(mFile, iNew, true);
  596.     EnableMenuItem(mFile, iOpen, true);
  597.     EnableMenuItem(mFile, iPreferences, true);
  598.     EnableMenuItem(mFile, iQuit, true);
  599.     EnableMenuItem(mEdit, iShowOrHideClipboard, true);
  600.     if (gHasAOCE)
  601.         EnableMenuItem(mDebug, iNewMailableWindow, true);
  602.     UpdateWindowMenu();
  603.     if (topWindowObj)
  604.         topWindowObj->SetupMenus();
  605.     DrawMenuBar();
  606. }
  607.  
  608. void HandleMouseDown(TWindow * theWindowObj,EventRecord *pEvent)
  609. {
  610.     WindowPtr    pWindow;
  611.     short        partCode;
  612.     TWindow    *pWindObj;
  613.  
  614.     partCode = FindWindow(pEvent->where, &pWindow);
  615.     pWindObj = GetWindowObject(pWindow);
  616.     
  617.     switch(partCode)
  618.     {
  619.         case    inMenuBar:
  620.             HandleSetupMenus(theWindowObj);
  621.             HandleMenu(theWindowObj, MenuSelect(pEvent->where));
  622.             break;
  623.             
  624.         case    inSysWindow:
  625.             SystemClick(pEvent,pWindow);
  626.             break;
  627.             
  628.         case    inContent:
  629.             if (pWindObj)
  630.             {
  631.                 SetPort(pWindow);
  632.                 pWindObj->Click(pEvent);
  633.             }
  634.             break;
  635.             
  636.         case    inDrag:
  637.             if (pWindObj)
  638.                 pWindObj->Drag(pEvent->where);
  639.             break;
  640.             
  641.         case    inGrow:
  642.             if (pWindObj)
  643.                 pWindObj->Grow(pEvent->where);
  644.             break;
  645.             
  646.         case    inGoAway:
  647.             if (TrackGoAway(pWindow,pEvent->where))
  648.                 HandleClose(pWindow);
  649.             break;
  650.  
  651.         case    inZoomIn:
  652.         case    inZoomOut:
  653.             if (TrackBox(pWindow,pEvent->where,partCode))
  654.                 if (pWindObj)
  655.                     pWindObj->Zoom(partCode);
  656.             break;
  657.             
  658.         default:
  659.             break;
  660.     }
  661. }
  662.  
  663. void    HandleUpdate(EventRecord * pEvent)
  664. {
  665.     WindowPtr    pWindow = (WindowPtr) pEvent->message;    
  666.     TWindow*    pWindObj = GetWindowObject(pWindow);
  667.         
  668.     if (pWindObj)
  669.     {
  670.         CSavePort  aSavePort(pWindow);
  671.         BeginUpdate(pWindow);
  672.             pWindObj->Draw();
  673.         EndUpdate(pWindow);
  674.     }
  675. }
  676.  
  677. void WindowCommand(WindowPtr pWindow, short theMenuID, short theItem)
  678. {
  679.     if (pWindow)
  680.     {
  681.         TWindow    *pWindObj = GetWindowObject(pWindow);
  682.         if (pWindObj)
  683.              pWindObj->HandleMenuCommand(theMenuID, theItem);
  684.     }
  685. }
  686.  
  687. void HandleClose(WindowPtr pWindow)
  688. {
  689.     if (pWindow)
  690.     {
  691.         short    windowKind = ((WindowPeek) pWindow)->windowKind;
  692.         if (windowKind < 0)
  693.             CloseDeskAcc(windowKind);
  694.         else
  695.         {
  696.             TWindow    *pWindObj = GetWindowObject(pWindow);
  697.             if 
  698.             (
  699.                 pWindObj && pWindObj->CanClose()
  700.                 && pWindObj->Close() && pWindObj->DeleteAfterClose()
  701.             )
  702.                 delete pWindObj;
  703.         }
  704.     }
  705. }
  706.